package com.baiduspring.web.user;

import com.baiduspring.dao.entity.User;
import com.baiduspring.dao.entity.UserDetails;
import com.baiduspring.error.BaiduSpringException;
import com.baiduspring.function.elasticsearch.operation.Doc;
import com.baiduspring.function.elasticsearch.operation.QueryInput;
import com.baiduspring.service.specialcolumn.SpecialColumnIndexEnum;
import com.baiduspring.service.user.FollowAuthorService;
import com.baiduspring.service.user.PrivateLetterService;
import com.baiduspring.service.user.UserDetailsService;
import com.baiduspring.service.user.UserService;
import com.baiduspring.utils.ResponseResult;
import com.baiduspring.utils.SystemCode;
import com.baiduspring.utils.elasticsearch.ElasticSearchUtils;
import com.baiduspring.vo.PrivateLetteVO;
import com.baiduspring.vo.ResultsVO;
import com.baiduspring.vo.UserDetailsVO;
import com.baiduspring.vo.UserVO;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 用户中心控制器
 *
 * @author xiongyan
 */
@RestController
@Scope("prototype")
@RequestMapping("/usercenter")
@Slf4j
public class UserCenterController {
    @Resource
    private UserService userService;
    @Resource
    private FollowAuthorService followAuthorService;
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private PrivateLetterService privateLetterService;

    @GetMapping("/{account}/about")
    public ModelAndView retrieveSetNewPassword(@PathVariable("account") Long account, HttpServletRequest request) {
        ModelAndView view = new ModelAndView("user/center/index");
        LoginStatus.status(request, view);

        userInfo(view, account);

        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchPhraseQuery("authorAccount", account));

        String[] indies = {SpecialColumnIndexEnum.SPECIAL_COLUMN_BLOG_INDEX.getValue()};
        String[] types = {SpecialColumnIndexEnum.SPECIAL_COLUMN_BLOG_TYPE.getValue()};

        Map<String, Class> outputFields = Maps.newHashMap();
        outputFields.put("id", String.class);
        outputFields.put("title", String.class);
        outputFields.put("orig", Integer.class);
        outputFields.put("label", String.class);
        outputFields.put("contentTxt", String.class);
        outputFields.put("authorAccount", Long.class);
        outputFields.put("uriMark", Long.class);
        outputFields.put("readNum", Integer.class);
        outputFields.put("collectNum", Integer.class);
        outputFields.put("likesNum", Integer.class);
        outputFields.put("updateDate", Long.class);

        Doc<String, SortOrder> sortFields = new Doc<>();
        sortFields.put("updateDate", SortOrder.DESC);

        QueryInput input = new QueryInput();
        input.setIndices(indies);
        input.setTypes(types);
        input.setOutputFields(outputFields);
        input.setSortFields(sortFields);

        ElasticSearchUtils.multipleFieldValueQuery(input, queryBuilder, ResultsVO.class, output -> {
            view.addObject("blogs", output.getResults());
            view.addObject("contribution", output.getTotal());
        });

        int countMyFollew = followAuthorService.countMyFollew(account);
        int countMyFans = followAuthorService.countMyFans(account);

        view.addObject("countMyFollew", countMyFollew);
        view.addObject("countMyFans", countMyFans);

        //todo 暂时跳到“个人动态”
        view.addObject("includeSelect", "personal_dynamics");

        return view;
    }

    /**
     * 编辑用户详情信息
     *
     * @param vo 参数
     * @return 返回保存结果
     */
    @RequestMapping(value = "/edit_info", method = RequestMethod.POST)
    public ResponseResult editInfo(HttpSession session, UserDetailsVO vo) {
        ResponseResult<Object> result = new ResponseResult<>();
        result.setCode(SystemCode.SUCCESS);
        result.setMessage("保存成功");

        Object o = session.getAttribute("user");
        if (Objects.isNull(o)) {
            result.setCode(SystemCode.FAIL);
            result.setMessage("登录已失效，请重新登录");
            return result;
        }

        User user = (User) o;

        try {
            userDetailsService.merge(vo.setAccount(user.getAccount()));
        } catch (BaiduSpringException e) {
            log.error("保存用户详细信息错误：{}", e);
            result.setCode(SystemCode.FAIL);
            result.setMessage(e.getErrorMsg());
        }

        return result;
    }

    /**
     * 上传用户头像
     *
     * @param photo 参数
     * @return 返回保存结果
     */
    @RequestMapping(value = "/upload/photo", method = RequestMethod.POST)
    public ResponseResult uploadUserPhoto(HttpSession session, String photo) {
        ResponseResult<Object> result = new ResponseResult<>();
        result.setCode(SystemCode.SUCCESS);
        result.setMessage("上传成功");

        Object o = session.getAttribute("user");
        if (Objects.isNull(o)) {
            result.setCode(SystemCode.FAIL);
            result.setMessage("登录已失效，请重新登录");
            return result;
        }

        User user = (User) o;

        try {
            userService.saveUserPhoto(user.getId(), photo);
        } catch (BaiduSpringException e) {
            result.setCode(SystemCode.FAIL);
            result.setMessage(e.getErrorMsg());
            return result;
        }

        return result;
    }

    @GetMapping("/editinfo_view")
    public ModelAndView editInfo(HttpSession session) {
        ModelAndView view = new ModelAndView("user/center/user-info");

        Object o = session.getAttribute("user");
        if (Objects.isNull(o)) {
            return null;
        }

        User user = (User) o;
        Optional<UserDetails> userDetails = userDetailsService.getByAccount(user.getAccount());
        view.addObject("userDetails", userDetails.get());

        return view;
    }

    /**
     * 私信
     *
     * @param session 参数
     * @return 视图
     */
    @GetMapping("/private_letter")
    public ModelAndView privateLetter(HttpServletRequest request, HttpSession session) {
        ModelAndView view = new ModelAndView("user/center/index");

        LoginStatus.status(request, view);

        Object o = session.getAttribute("user");
        if (Objects.isNull(o)) {
            return null;
        }

        User user = (User) o;
        Optional<List<PrivateLetteVO>> privateLetteVOList = this.privateLetterService.getPrivateLetterLishByAddressee(user.getAccount());
        privateLetteVOList.ifPresent(privateLetteVOS -> view.addObject("privateLettes", privateLetteVOS));

        userInfo(view, user.getAccount());

        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchPhraseQuery("authorAccount", user.getAccount()));

        String[] indies = {SpecialColumnIndexEnum.SPECIAL_COLUMN_BLOG_INDEX.getValue()};
        String[] types = {SpecialColumnIndexEnum.SPECIAL_COLUMN_BLOG_TYPE.getValue()};

        QueryInput input = new QueryInput();
        input.setIndices(indies);
        input.setTypes(types);

        Long conditions = ElasticSearchUtils.totalMultipleConditions(input, queryBuilder);
        view.addObject("contribution", conditions);

        int countMyFollew = followAuthorService.countMyFollew(user.getAccount());
        int countMyFans = followAuthorService.countMyFans(user.getAccount());

        view.addObject("countMyFollew", countMyFollew);
        view.addObject("countMyFans", countMyFans);

        view.addObject("includeSelect", "private_letter");
        return view;
    }

    private void userInfo(ModelAndView view, Long account) {
        Optional<User> optional = userService.getByAccount(account);
        optional.ifPresent(u -> {
            UserVO userVO = new UserVO();
            UserDetailsVO userDetailsVO = new UserDetailsVO();

            BeanUtils.copyProperties(u, userVO);
            BeanUtils.copyProperties(u.getUserDetails(), userDetailsVO);

            userVO.setUserDetails(userDetailsVO);
            view.addObject("user", userVO);
        });
    }

}
